package org.jsola.hr.provider.impl;

import lombok.extern.slf4j.Slf4j;
import org.jsola.admin.constant.AdminConstants;
import org.jsola.admin.dto.AsyncTaskDetailAddDTO;
import org.jsola.admin.dto.DictItemUpdateDTO;
import org.jsola.admin.dto.HeaderFieldsAddDTO;
import org.jsola.admin.dto.HeaderSortDTO;
import org.jsola.admin.entity.*;
import org.jsola.admin.query.HeaderFieldsQuery;
import org.jsola.admin.query.HeaderFieldsTemplateQuery;
import org.jsola.admin.service.*;
import org.jsola.admin.vo.*;
import org.jsola.common.ArrayKit;
import org.jsola.common.SafeKit;
import org.jsola.common.StrKit;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.NumberKit;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.service.*;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrConstants.TX;
import static org.jsola.hr.constant.HrPermissionConstants.HR_SUBJECT_TYPE;

/**
 * @author JanusMix
 */
@Slf4j
@Service("hrAdminProviderService")
public class AdminProviderServiceImpl implements IAdminProviderService {

    @Autowired
    private IAdminPermissionService adminPermissionService;

    @Autowired
    private ISubjectTypeService subjectTypeService;

    @Autowired
    private IMenuService menuService;

    @Autowired
    private IAreaService areaService;

    @Autowired
    private IHrPermissionService hrPermissionService;

    @Autowired
    private ISiteService siteService;

    @Autowired
    private IGroupCompanyService groupCompanyService;

    @Autowired
    private IGroupCityService groupCityService;

    @Autowired
    private IHeaderFieldsService headerFieldsService;

    @Autowired
    private IDictItemService dictItemService;

    @Autowired
    private IHeaderFieldsTemplateService headerFieldsTemplateService;

    @Autowired
    private IDefaultVariableService defaultVariableService;

    @Autowired
    private IDefaultFieldService defaultFieldService;

    @Autowired
    private IAsyncTaskService asyncTaskService;

    @Autowired
    private IAsyncTaskDetailService asyncTaskDetailService;

    @Autowired
    private IEmpSocRelatedService empSocRelatedService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IProductService productService;

    @Autowired
    private ISocProgService socProgService;

    @Autowired
    private IEventHandlingService eventHandlingService;

    @Autowired
    private IMissionCenterService missionCenterService;

    @Override
    public List<String> selectSubjectTypesBySiteAndType(String subjectType, String siteId) {
        return subjectTypeService.selectSubjectTypesBySiteAndType(subjectType, siteId);
    }

    @Override
    public AllPermissionVO getAllPermission(String userId, String subjectId, String subjectType, String siteId) {
        AllPermissionVO allPermissionVO = adminPermissionService.getAllPermission(userId, subjectId, subjectType, siteId);
        List<MenuVO> menuList = allPermissionVO.getMenuList();
        if (CollectionUtils.isEmpty(menuList)) {
            return allPermissionVO;
        }
        //只取moduleType为hr的
        allPermissionVO.setMenuList(menuList.stream().filter(menuVO -> HR_SUBJECT_TYPE.equals(menuVO.getModuleType())).collect(Collectors.toList()));
        return allPermissionVO;
    }

    @Override
    public AllPermissionVO getAllPermission2(String userId, String subjectId, String subjectType, String siteId) {
        AllPermissionVO allPermissionVO = adminPermissionService.getAllPermission(userId, subjectId, subjectType, siteId);
        List<MenuVO> menuList = allPermissionVO.getMenuList();
        if (CollectionUtils.isEmpty(menuList)) {
            return allPermissionVO;
        }
        //只取moduleType为hr的
        allPermissionVO.setMenuList(menuList.stream().filter(menuVO -> HR_SUBJECT_TYPE.equals(menuVO.getModuleType())).collect(Collectors.toList()));
        return allPermissionVO;
    }

    @Override
    public List<MenuVO> getMenuList(List<String> subjectTypeList) {
        List<MenuDO> menuList = menuService.selectBySubjectTypes(subjectTypeList);
        return menuList.stream().map(menuDO -> menuDO.to(MenuVO.class)).collect(Collectors.toList());
    }

    @Override
    public List<AreaListVO> listAreaByCompany(String companyId, TokenUser tokenUser) {
        // 所有地区
        List<AreaListVO> allArealist = areaService.getAllList();

        // 用户是不是admin
        boolean userIsAdmin = hrPermissionService.isAdmin(tokenUser.getUserId(), tokenUser.getSiteId());
        // 用户是不是总公司的成员
        boolean userIsSuperCompany = hrPermissionService.isSuperCompanyAdmin(tokenUser.getUserId(), tokenUser.getSiteId());
        // admin和总公司成员可以看全部公司
        if (!userIsAdmin && !userIsSuperCompany) {
            List<String> groupIdList = groupCompanyService.checkCompanyIsChild(companyId, tokenUser.getSiteId());
            if (!CollectionUtils.isEmpty(groupIdList)) {
                // 是子公司
                // 获取子公司分管的区域
                List<String> cityCodeList = groupCityService.listGroupCityCode(groupIdList, tokenUser.getSiteId());
                if (CollectionUtils.isEmpty(cityCodeList)) {
                    return null;
                }
                if (cityCodeList.size() == 1 && "all".equals(cityCodeList.get(0))) {
                    return null;
                }
                // 获取有权限的地区,地区本身或者父地区
                List<Long> cityIdList = new ArrayList<>();
                cityCodeList.parallelStream().forEach(
                        cityCode -> {
                            if (NumberKit.isNumeric(cityCode)) {
                                AreaVO areaVO = areaService.getAreaById(Long.valueOf(cityCode));
                                if (Objects.nonNull(areaVO)) {
                                    // 城市本身
                                    cityIdList.add(areaVO.getId());
                                    // 获取地区的父城市
                                    List<Long> parentCityIdList = new ArrayList<>();
                                    getAreaParent(parentCityIdList, areaVO.getParentId());
                                    cityIdList.addAll(parentCityIdList);
                                }
                            }
                        }
                );
                if (CollectionUtils.isEmpty(cityIdList)) {
                    return null;
                }
                // 有权限的区域
                return allArealist.stream()
                        .filter(area -> cityIdList.contains(area.getId()))
                        .collect(Collectors.toList());
            } else {
                // 不是分公司,返回全部地区
                return allArealist;
            }
        }
        return allArealist;
    }

    @Override
    public String getAreaNameById(String areaId) {
        return areaService.getAreaNameById(Long.valueOf(areaId), "/");
    }

    @Override
    public AreaReduceVO getAreaByName(List<AreaReduceVO> areaList, String areaNames) {
        List<AreaReduceVO> list = areaService.getAreaByName(areaList, areaNames, "/");
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public AreaDO getAreaByName(String areaName, String parentAreaName) {
        return areaService.getAreaByName(areaName, parentAreaName);
    }

    /**
     * 获取地区的父城市
     *
     * @param parentCityIdList 父城市
     * @param parentId         父地区id
     */
    private void getAreaParent(List<Long> parentCityIdList, Long parentId) {
        AreaVO areaVO = areaService.getAreaById(parentId);
        if (Objects.nonNull(areaVO)) {
            // 存在,继续获取
            parentCityIdList.add(areaVO.getId());
            // 迭代继续获取
            getAreaParent(parentCityIdList, areaVO.getParentId());
        }
    }

    @Override
    public SiteVO selectSiteById(String siteId, TokenUser tokenUser) {
        return siteService.selectById(siteId, tokenUser.getSiteId());
    }

    @Override
    public SiteVO selectSiteBySecDomain(String secDomain) {
        return siteService.selectBySecDomain(secDomain);
    }

    @Override
    public List<SiteDO> selectByIds(List<String> siteIdList) {
        return siteService.selectByIds(siteIdList);
    }

    @Override
    public List<AreaReduceVO> listAllArea() {
        return areaService.getAllListReduce();
    }

    @Override
    public Map<String, SiteDO> selectSiteMap() {
        return siteService.selectSiteMap();
    }

    @Override
    public int updateSitePic(String picUrl, TokenUser tokenUser) {
        return siteService.updateSitePic(picUrl, tokenUser);
    }

    @Override
    public String selectAreaById(String areaId) {
        AreaVO areaVO = areaService.getAreaById(Long.parseLong(areaId));
        if (ObjectUtils.isEmpty(areaVO)) {
            return null;
        }
        return areaVO.getName();
    }

    @Override
    public AreaVO selectAreaVOById(String areaId) {
        return areaService.getAreaById(Long.parseLong(areaId));
    }

    @Override
    public AreaVO selectAreaVOById(Long areaId) {
        return areaService.getAreaById(areaId);
    }

    @Override
    public List<HeaderFieldsDO> selectHeaderFieldsByModuleCode(String companyId, String moduleCode, TokenUser tokenUser) {
        return headerFieldsService.selectByModuleCode("company", companyId, moduleCode, tokenUser);
    }

    @Override
    public List<HeaderFieldsDO> selectMyselfHeaderFieldsBySourceId(String subjectType, String subjectId
            , String moduleCode, String sourceId, TokenUser tokenUser) {
        return headerFieldsService.selectMyselfBySourceId(subjectType, subjectId, moduleCode, sourceId, tokenUser);
    }

    @Override
    public List<DictItemDO> selectLikeByCodeAndName(String value, String dictCode) {
        return dictItemService.selectLikeByCodeAndName(value, dictCode);
    }

    @Override
    public DictItemDO selectByCodeAndKey(String dictCode, String dictItemKey) {
        return dictItemService.selectByCodeAndKey(dictCode, dictItemKey);
    }

    @Override
    public List<DictItemDO> selectByDictCode(String dictCode) {
        return dictItemService.selectProvince(dictCode);
    }

    @Override
    public List<DictItemDO> selectDictByParentId(String dictCode, String parentId) {
        return dictItemService.selectByParentId(dictCode, parentId);
    }

    @Override
    public List<MenuVO> listByPermissionStr(List<String> permissionStringList) {
        return menuService.listByPermisionStr(permissionStringList);
    }

    @Override
    public List<DictItemDO> selectAllSocItem() {
        List<DictItemDO> itemList = new ArrayList<>();
        itemList.addAll(dictItemService.selectProvince("1213"));
        itemList.addAll(dictItemService.selectProvince("1214"));
        itemList.addAll(dictItemService.selectProvince("1215"));
        return itemList;
    }

    @Override
    public void bachSave(List<DictItemDO> insertList) {
        dictItemService.bachSave(insertList);
    }

    @Override
    public String getAreaNameByIds(String bankPlaceIds, String regex) {
        if (StrKit.isEmpty(bankPlaceIds)) {
            return "";
        }
        String bankPlace = "";
        // 去除"[","]"符号
        bankPlaceIds = bankPlaceIds.replaceAll("\\[", "").replaceAll("]", "");
        List<String> bankPlaceIdList = ArrayKit.split(bankPlaceIds);
        if (StrKit.isEmpty(regex)) {
            regex = "-";
        }
        if (CollectionUtils.isEmpty(bankPlaceIdList)) {
            return "";
        }
        // 一组地区id
        if (bankPlaceIdList.size() > 1) {
            StringBuilder bankPlaceBuilder = new StringBuilder();
            for (String bankPlaceId : bankPlaceIdList) {
                String bankPlaceItem = this.selectAreaById(bankPlaceId);
                bankPlaceBuilder.append(regex);
                bankPlaceBuilder.append(bankPlaceItem);
            }
            bankPlace = bankPlaceBuilder.toString().replaceFirst(regex, "");
        }
        // 地区id只有一个
        else if (bankPlaceIdList.size() == 1) {
            Long aLong = SafeKit.getLong(bankPlaceIdList.get(0));
            if (aLong != null) {
                bankPlace = getAreaName(aLong, bankPlace, regex);
            } else {
                bankPlace = bankPlaceIdList.get(0);
            }
        }
        return bankPlace;
    }

    private String getAreaName(Long areaId, String areaName, String regex) {
        if (Objects.isNull(areaId)) {
            return null;
        }
        AreaVO areaVO = this.selectAreaVOById(areaId);
        if (Objects.nonNull(areaVO)) {
            if (StrKit.isEmpty(areaName)) {
                areaName = areaVO.getName();
            } else {
                areaName = areaVO.getName() + regex + areaName;
            }
            if (areaVO.getParentId() != 0) {
                areaName = getAreaName(areaVO.getParentId(), areaName, regex);
            }
        }
        return areaName;
    }

    @Override
    public String getAreaNameByIds(String bankPlaceIds) {
        return getAreaNameByIds(bankPlaceIds, "-");
    }

    @Override
    public List<HeaderFieldsListVO> getHeadField(HeaderFieldsQuery headerFieldsQuery, TokenUser tokenUser) {
        return headerFieldsService.select(headerFieldsQuery, tokenUser.getSiteId());
    }

    @Override
    public List<HeaderFieldsTemplateListVO> getAllTemplateField(String moduleCode) {
        TokenUser tokenUser = new TokenUser();
        tokenUser.setSiteId(AdminConstants.DEFAULT);
        HeaderSortDTO headerSortDTO = headerFieldsTemplateService.selectAll(moduleCode, tokenUser);
        List<HeaderFieldsTemplateListVO> headerFieldsTemplateListVOList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(headerSortDTO.getCanSeeList())) {
            headerFieldsTemplateListVOList.addAll(headerSortDTO.getCanSeeList().parallelStream()
                    .map(headerFieldsTemplateUpdateDTO -> headerFieldsTemplateUpdateDTO.to(HeaderFieldsTemplateListVO.class)).collect(Collectors.toList()));
        }
        if (!CollectionUtils.isEmpty(headerSortDTO.getNotSeeList())) {
            headerFieldsTemplateListVOList.addAll(headerSortDTO.getNotSeeList().parallelStream()
                    .map(headerFieldsTemplateUpdateDTO -> headerFieldsTemplateUpdateDTO.to(HeaderFieldsTemplateListVO.class)).collect(Collectors.toList()));
        }
        return headerFieldsTemplateListVOList;
    }

    @Override
    public List<DefaultVariableDO> selectDefaultVariableByTemplateId(Long templateId) {
        return defaultVariableService.selectByTemplateId(templateId);
    }

    @Override
    public List<DefaultVariableDO> selectDefaultVariableByTemplateIds(List<Long> templateIds) {
        return defaultVariableService.selectByTemplateIds(templateIds);
    }

    @Override
    public List<DefaultFieldDO> selectDefaultFieldByIdsNotSiteId(List<String> defaultFieldIds) {
        return defaultFieldService.selectByIdsNotSiteId(defaultFieldIds);
    }

    @Override
    public List<HeaderFieldsTemplateListVO> selectHeaderByModuleAndName(String moduleCode, String fieldName) {
        HeaderFieldsTemplateQuery headerFieldsTemplateQuery = new HeaderFieldsTemplateQuery();
        headerFieldsTemplateQuery.setModuleCode(moduleCode);
        headerFieldsTemplateQuery.setName(fieldName);
        return headerFieldsTemplateService.select(headerFieldsTemplateQuery, AdminConstants.DEFAULT);
    }

    @Override
    public HeaderFieldsVO getHead(HeaderFieldsQuery headerFieldsQuery, TokenUser tokenUser) {
        return headerFieldsService.getHead(headerFieldsQuery, tokenUser);
    }

    @Override
    @Transactional(value = TX, rollbackFor = Exception.class)
    public AsyncTaskDO saveAsyncTask(AsyncTaskDO asyncTaskDO, TokenUser tokenUser) {
        return asyncTaskService.save(asyncTaskDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = TX, rollbackFor = Exception.class)
    public int updateAsyncTask(AsyncTaskDO asyncTaskDO, TokenUser tokenUser) {
        return asyncTaskService.updateByIdSelective(asyncTaskDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = TX, rollbackFor = Exception.class)
    public int updateTaskFail(String asyncTaskId) {
        return asyncTaskService.taskFail(asyncTaskId);
    }

    @Override
    public int finishSubTask(String asyncTaskId) {
        return asyncTaskService.finishSubTask(asyncTaskId);
    }

    @Override
    @Transactional(value = TX, rollbackFor = Exception.class)
    public AsyncTaskDetailVO saveAsyncDetail(AsyncTaskDetailAddDTO asyncTaskDetailAddDTOList, TokenUser tokenUser) {

        return asyncTaskDetailService.save(asyncTaskDetailAddDTOList, tokenUser);
    }

    @Override
    @Transactional(value = TX, rollbackFor = Exception.class)
    public List<AsyncTaskDetailVO> batchSaveAsyncDetail(List<AsyncTaskDetailAddDTO> asyncTaskDetailAddDTOList,
                                                        TokenUser tokenUser) {
        return asyncTaskDetailService.batchSave(asyncTaskDetailAddDTOList, tokenUser);
    }

    @Override
    public List<HeaderFieldsDO> selectByModuleCodeAndUser(String companyId, String moduleCode, TokenUser tokenUser) {
        return headerFieldsService.selectByModuleCodeAndUser("company", companyId, moduleCode, tokenUser);
    }

    @Override
    public List<HeaderFieldsTemplateDO> selectByCodeAndGroup(String moduleCode, String fieldGroup) {
        return headerFieldsTemplateService.selectByCodeAndGroup(moduleCode, fieldGroup);
    }

    @Override
    public void bachSaveHeaderFields(List<HeaderFieldsAddDTO> addList, TokenUser tokenUser) {
        headerFieldsService.batchSave(addList, tokenUser);
    }

    @Override
    public void deleteByModuleCodeAndUser(String companyId, String moduleCode, TokenUser tokenUser) {
        headerFieldsService.deleteByModuleCodeAndUser("company", companyId, moduleCode, tokenUser);
    }

    @Override
    public void updateDictItem(DictItemUpdateDTO dictItemUpdateDTO, TokenUser tokenUser) {
        DictItemDO dictItem = dictItemService.selectDOById(dictItemUpdateDTO.getId(), tokenUser.getSiteId());
        // value值没变 直接返回
        if (dictItemUpdateDTO.getDictItemValue().equals(dictItem.getDictItemValue())) {
            return;
        }
        // 更新数据
        dictItemService.update(dictItemUpdateDTO, tokenUser);
        // 更新各自业务
        // 更新社保
        empSocRelatedService.updateDict(dictItem, dictItemUpdateDTO, tokenUser);
        socProgService.updateDict(dictItem, dictItemUpdateDTO, tokenUser);
        // 更新花名册
        empInfoService.updateDict(dictItem, dictItemUpdateDTO, tokenUser);
        // 更新产品标签
        productService.updateDict(dictItem, dictItemUpdateDTO, tokenUser);
        // 更新事件处理
        eventHandlingService.updateDict(dictItem, dictItemUpdateDTO, tokenUser);
        // 更新任务派单
        missionCenterService.updateDict(dictItem, dictItemUpdateDTO, tokenUser);
    }

    @Override
    public int deleteDictItemByIds(TokenUser tokenUser, String dictItemId) {
        // 检查是否被使用
        DictItemDO dictItem = dictItemService.selectDOById(dictItemId, tokenUser.getSiteId());
        if (dictItem == null) {
            return 1;
        }
        // 查询社保
        Integer integer = empSocRelatedService.selectDict(dictItem, tokenUser);
        ParamException.isFalse(integer > 0, "修改前的值已被使用，请刷新后重试");
        socProgService.deleteDict(dictItem, tokenUser);
        // 查询花名册
        integer = empInfoService.selectDict(dictItem, tokenUser);
        ParamException.isFalse(integer > 0, "修改前的值已被使用，请刷新后重试");
        // 查询产品标签
        integer = productService.selectDict(dictItem, tokenUser);
        ParamException.isFalse(integer > 0, "修改前的值已被使用，请刷新后重试");
        // 查询事件处理
        integer = eventHandlingService.selectDict(dictItem, tokenUser);
        ParamException.isFalse(integer > 0, "修改前的值已被使用，请刷新后重试");
        // 查询任务派单
        integer = missionCenterService.selectDict(dictItem, tokenUser);
        ParamException.isFalse(integer > 0, "修改前的值已被使用，请刷新后重试");
        return dictItemService.deleteByIds(tokenUser, dictItemId);
    }

    @Override
    public List<DictItemDO> selectAllDictItem(String keyWord, String dictCode, TokenUser tokenUser) {
        return dictItemService.selectAllDictItem(keyWord, dictCode, tokenUser);
    }


}
